(function() {

	var D = QW.Dom,
		O = QW.ObjectH,
		mix=QW.ObjectH.mix,
        DomU=QW.DomU,
        createElement=DomU.createElement,
        EventH=QW.EventH,
        target=EventH.getTarget,
        keyCode=EventH.getKeyCode,
        preventDefault=EventH.preventDefault,
        CustEvent=QW.CustEvent,
        NodeH=QW.NodeH,
        addClass=NodeH.addClass,
        removeClass=NodeH.removeClass,
        setStyle=NodeH.setStyle,
        getXY=NodeH.getXY,
		getSize = NodeH.getSize,
        ancestorNode=NodeH.ancestorNode,
        on=QW.EventTargetH.addEventListener,
		forEach = QW.ArrayH.forEach,
		appendChild = NodeH.appendChild,
        Browser=QW.Browser;

	// private methods and properties.
	_id = 'qwui-dialog',
	_ids = [],
	_current_dlg = null,
	_isIE6 = (Browser.ie && Browser.ie === '6.0') ? true: false,
	_cache = {},

	//button callback. _button_callback[button id] = function.
	_button_callback = {}

	_CSS_DLG = 'qwui-dialog',
	_CSS_BTN_CLOSE = 'qwui-dialog-close',
	_CSS_DIV_SHD = 'qwui-dialog-shd',
	_CSS_DIV_CONTENT = 'qwui-dialog-content',
	_CSS_IFRM = 'qwui-dialog-iframe',

	_TXT_CONFIRM = '确定',
	_TXT_CANCEL = '取消',
	_TXT_TIP = '提示',
	_TXT_LOADING = '下载中，请稍候...',

	_templ = '<div id="{ID}" class="' + _CSS_DLG + '" style="{CSS_ISHIDE}">\
				<span class="' + _CSS_DIV_SHD + '"></span>\
				<div class="' + _CSS_DIV_CONTENT + '">\
					{TITLE}\
					<div class="bd"></div>\
                    {BN_CLOSE}\
				</div>\
			</div>',
	_templ_btn_close = '<a href="#" class="' + _CSS_BTN_CLOSE + '">X</a>',
	_templ_title = '<div class="hd"><h3>{TITLE}</h3></div>',
	_templ_iframe = '<iframe class="' + _CSS_IFRM + '"></iframe>',

	_button_config = {
		'confirm': {
			text: _TXT_CONFIRM,
			method: function(o) {
				o.close();
			}
		},
		'cancel': {
			text: _TXT_CANCEL,
			method: function(o) {
				o.close();
			}
		}
	},

	_default_config = {
		url: '',
		content: '',
		title: _TXT_TIP,
		width: 0,
		height: 0,
		visible: false,
		iframe: false,
		maxWidth: 960,
		autoupdate: false,
		cache: true,
		buttons: [],
		callback: null,
		dataType: 'text',
		isStick: false,
		isHideClose: false,
		isHideTitle: false
	},

	_formCollection = function(frm) {
		var els = frm.elements,
		i = 0,
		el, data = [],
		getValue = {
			'select-one': function(el) {
				return encodeURIComponent(el.name) + '=' + encodeURIComponent(el.options[el.selectedIndex].value);
			},
			'select-multiple': function(el) {
				var i = 0,
				opt, values = [];
				for (; opt = el.options[i++];) {
					if (opt.selected) {
						values.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(opt.value));
					}
				}
				return values.join('&');
			},
			'radio': function(el) {
				if (el.checked) {
					return encodeURIComponent(el.name) + '=' + encodeURIComponent(el.value);
				}
			},
			'checkbox': function(el) {
				if (el.checked) {
					return encodeURIComponent(el.name) + '=' + encodeURIComponent(el.value);
				}
			}
		};
		for (; el = els[i++];) {
			if (getValue[el.type]) {
				data.push(getValue[el.type](el));
			} else {
				data.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(el.value));
			}
		}

		return data.join('&').replace(/\&{2,}/g, '&');
	},

	dialog = function(cfg) {
		var c = cfg || {};
		this.config = mix(_default_config,c,1);
		this.init();
	};

	dialog.prototype = {
		init: function() {
			if (!this.config) {
				return;
			}

			this.render();
			this.bind();
		},

		render: function() {
			var cfg = this.config,
			id = _id + _ids.length;

			_ids.push(id);

			appendChild(document.body,_templ.replace('{ID}', id).replace('{CSS_ISHIDE}', cfg.visible ? '': 'visibility:hidden;top:-999em;left:-999em;').replace('{TITLE}', _templ_title.replace('{TITLE}', cfg.title)).replace('{BN_CLOSE}', _templ_btn_close));

			this.id = id;
			this.node = D.query('#' + id)[0];
			this.title = D.query('.hd', this.node)[0];
			this.body = D.query('.bd', this.node)[0];
			this.btnClose = D.query('.' + _CSS_BTN_CLOSE, this.node)[0];
			this.shadow = D.query('.' + _CSS_DIV_SHD, this.node)[0];
			this.iframe = D.query('.' + _CSS_IFRM, this.node)[0];

			this.set(cfg);
		},

		bind: function() {
			var o = this;
			on(document,'resize',function(){
				if (_isIE6) {
					return;
				}
				o.updatePosition();
			});

			on(document,'resize',function(){
				if (!_isIE6) {
					return;
				}
				o.updatePosition();
			});

			on(this.btnClose,'click',function(e) {
				o.close();
				e.preventDefault();
			});
			
			on(document.body,'keypress',function(){
				if (e.keyCode === 27) {
					o.close();
				}
			});
		},

		updateSize: function() {
			var w = getSize(this.node).width,
			h,
			screen_height = DomU.getDocRect().height,
			cfg = this.config;
			
			setStyle(this.body,{
				'height': 'auto',
				'overflow-x': 'visible',
				'overflow-y': 'visible'
			});

			h = getSize(this.node).height;

			if (w > cfg.maxWidth) {
				w = cfg.maxWidth;
				setStyle(this.node,'width',w + 'px');
			}

			if (h > screen_height) {
				setStyle(this.body,{
					'height': (screen_height - 150) + 'px',
					'overflow-x': 'hidden',
					'overflow-y': 'auto'
				});
			}

			h = getSize(this.node).height;

			this.shadow.style.width = (w + 16) + 'px';
			this.shadow.style.height = (h + 16) + 'px';
			console.log(this.shadow);
			if(this.iframe){
				this.iframe.style.width = w + 16
				this.iframe.style.height = h + 16;
			}

		},

		updatePosition: function() {
			if (this.config.isStick)
				return;
			var w = getSize(this.node).width,
			h = getSize(this.node).height,
			win = DomU.getDocRect(),
			scrollTop = win.scrollY,
			t = _isIE6 ? scrollTop : 0;
			setStyle(this.node,{
				left: Math.floor(win.width / 2 - w / 2 - 8) + 'px',
				top: Math.floor(win.height / 2 - h / 2 - 8) + t + 'px'
			});
		},

		set: function(cfg) {
			var title, close, html_str, el, id = this.id,
			num = [],
			that = this,
			genId = function(str) {
				num.push(0);
				return id + '-' + str + '-' + num.length;
			};

			if (!cfg) {
				return;
			}

			// set width and height.
			if (cfg.width) {
				setStyle(this.node,'width', cfg.width + 'px');
				this.config.width = cfg.width;
			}

			if (cfg.height) {
				setStyle(this.node,'height', cfg.height + 'px');
				this.config.height = cfg.height;
			}

			// set buttons
			if (QW.ObjectH.isArray(cfg.buttons) && cfg.buttons[0]) {
				el = D.query('.ft', this.node);
				console.log(el);
				html_str = [];
				forEach(cfg.buttons,function(el){
					var bn = el,
					bnId = genId('bn');
					console.log(el);
					if (typeof bn === 'string' && _button_config[bn]) {
						html_str.push('<span class="bn-flat"><input type="button" id="' + bnId + '" class="' + _id + '-bn-' + bn + '" value="' + _button_config[bn].text + '" /></span> ');
						_button_callback[bnId] = _button_config[bn].method;
					} else {
						html_str.push('<span class="bn-flat"><input type="button" id="' + bnId + '" class="' + _id + '-bn" value="' + bn.text + '" /></span> ');
						_button_callback[bnId] = bn.method;
					}
				});

				if (!el[0]) {
					appendChild(this.body.parentNode,'<div class="ft">' + html_str.join('') + '</div>');
					el = this.body.parentNode;
				} else {
					el.innerHTML = html_str.join('');
				}

				// bind event.
				on(D.query('.ft input', this.node)[0],'click',function(e){
					var func = _button_callback[this.id];
					console.log(func);
					if (func) {
						func(that);
					}
				});

				this.footer = D.query('.ft', this.node)[0];
			} else {
				this.footer = D.query('.ft', this.node)[0];
				if(this.footer)
					this.footer.innerHTML = '';
			}

			// set hidden close button
			if (typeof cfg.isHideClose !== 'undefined') {
				if (cfg.isHideClose) {
					this.btnClose.style.display = 'none';
				} else {
					this.btnClose.style.display = '';
				}
				this.config.isHideClose = cfg.isHideClose;
			}

			// set hidden title 
			if (typeof cfg.isHideTitle !== 'undefined') {
				if (cfg.isHideTitle) {
					this.title.style.display = 'none';
				} else {
					this.title.style.display = '';
				}
				this.config.isHideTitle = cfg.isHideTitle;
			}

			// set title.
			if (cfg.title) {
				this.setTitle(cfg.title);
				this.config.title = cfg.title;
			}

			// set enable iframe
			if (typeof cfg.iframe !== 'undefined') {
				console.log(cfg.iframe);
				if (!cfg.iframe) {
					if (this.iframe){
						this.iframe.style.display = 'none';
					}
				} else if (!this.iframe) {
					nodeH.insertAdjacentHTML(this.node,'beforebegin', _templ_iframe);
					this.iframe = D.query('.' + _CSS_IFRM, this.node)[0];
					console.log(this.iframe);
				} else {
					this.iframe.style.display = '';
				}
				this.config.iframe = cfg.iframe;
			}

			// set content.
			if (cfg.content) {
				this.body.innerHTML = typeof cfg.content === 'object' ? D.query(cfg.content)[0].innerHTML() : cfg.content;
				this.config.content = cfg.content;
			}

			// fetch content by URL.
			if (cfg.url) {
				if (cfg.cache && _cache[cfg.url]) {
					if (cfg.dataType === 'text' || ! cfg.dataType) {
						this.setContent(_cache[cfg.url]);
					}
					if (cfg.callback) {
						cfg.callback(_cache[cfg.url], this);
					}
				} else if (cfg.dataType === 'json') {
					this.setContent(_TXT_LOADING);
					if (this.footer) {
						this.footer.style.display = 'none';
					}
					$.getJSON(cfg.url, function(data) {
						that.footer.style.display = '';
						_cache[cfg.url] = data;
						if (cfg.callback) {
							cfg.callback(data, that);
						}
					});
				} else {
					this.setContent(_TXT_LOADING);
					if (this.footer) {
						this.footer.style.display = 'none';
					}
					Ajax.get(cfg.url,function(content){
						_cache[cfg.url] = content;
							if (that.footer) {
								that.footer.style.display = '';
							}
							that.setContent(content);
							if (cfg.callback) {
								cfg.callback(content, that);
							}
					});
				}
			}

			var pos = cfg.position;
			if (pos) {
				setStyle(this.node ,{
					left: pos[0] + 'px',
					top: pos[1] + 'px'
				});
			}

			if (typeof cfg.autoupdate === "boolean") {
				this.config.autoupdate = cfg.autoupdate;
			}
			if (typeof cfg.isStick === "boolean") {
				if (cfg.isStick) {
					this.node.style.position = "absolute";
				} else {
					this.node.style.position = "";
				}
				this.config.isStick = cfg.isStick;
			}

			return this.update();
		},

		update: function() {
			this.updateSize();
			this.updatePosition();
			return this;
		},

		setContent: function(str) {
			this.body.innerHTML(str);
			return this.update();
		},

		setTitle: function(str) {
			D.query('h3', this.title)[0].innerHTML = str;
			return this;
		},

		// submit form in dialog
		submit: function(callback) {
			var that = this,
			frm = D.query('form', this.node)[0];
			frm.on('submit',function(e) {
				EventH.preventDefaulte(e);

				var url = this.getAttribute('action', 2),
				type = this.getAttribute('method') || 'get',
				data = _formCollection(this);
				var success = function(da) {
					if (callback) {
						callback(da);
					}
				};
				if (type.toLowerCase()==='get'){
					Ajax.get(url,data,success);
				}else{
					Ajax.post(url,data,success);
				}

//				$[type.toLowerCase()](url, data, function(da) {
//					if (callback) {
//						callback(da);
//					}
//				},
//				'json');
			});

			frm.submit();
		},

		open: function() {
			appendChild(document.body,this.node);
			setStyle(this.node,{'visibility':'visible','display':'block'});
			var self = this, bd = self.body;
			self.contentHeight = bd.offsetHeight;
			this.watcher = !this.config.autoupdate ? 0 : setInterval(function(){
				if (bd.offsetHeight === self.contentHeight) {
					return;
				}
				self.update();
				self.contentHeight = bd.offsetHeight;
			}, 100);
			return this;
		},

		close: function() {
			this.node.style.display = 'none';
			clearInterval(this.watcher);
			return this;
		}
	};

	// add to qwui
	var Dialog = function(cfg, isMulti) {
		// use sigleton dialog mode by default.
		if (!isMulti && _current_dlg) {
			return cfg ? _current_dlg.set(cfg) : _current_dlg;
		}

		if (!_current_dlg && ! isMulti) {
			_current_dlg = new dialog(cfg);
			return _current_dlg;
		}

		return new dialog(cfg);
	};
	
	QW.provide('Dialog', Dialog);

})();
